package com.sky.business.sys.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sky.business.sys.domain.CameraConfig;
import com.sky.business.sys.domain.SystemConfig;
import com.sky.business.sys.domain.TrackTask;
import com.sky.business.sys.event.EdgeEndTrackingEvent;
import com.sky.business.sys.service.CameraConfigService;
import com.sky.business.sys.service.DispatcherService;
import com.sky.business.sys.service.SystemConfigService;
import com.sky.business.sys.service.TrackTaskService;
import com.sky.business.sys.util.MQTTClientUtils;
import com.sky.common.config.CacheConstants;
import com.sky.common.utils.GeoUtils;
import com.sky.common.utils.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 调度服务实现
 *
 */
@Slf4j
@Service
public class DispatcherServiceImpl implements DispatcherService {

    @Autowired
    private TrackTaskService trackTaskService;

    @Autowired
    private CameraConfigService cameraConfigService;

    @Autowired
    private SystemConfigService systemConfigService;


    public static ObjectMapper objectMapper = new ObjectMapper().setTimeZone(SimpleTimeZone.getTimeZone("GMT+8"));


    @Override
    @Async("miniThreadPoolTaskExecutor")
    public void stopOtherDeviceTracking(String taskId, List<String> deviceIdList) {
        List<TrackTask> otherDeviceTrackTaskList = trackTaskService.findByTaskIdAndDeviceIdNotIn( taskId,deviceIdList);
        endTracking(otherDeviceTrackTaskList);
    }

    @Async("miniThreadPoolTaskExecutor")
    @Override
    public void endTracking(List<TrackTask> trackTaskList) {
        SystemConfig systemConfig = systemConfigService.getSystemConfig();
        Date now = new Date();
        Set<String> taskDeviceSet = new HashSet<>();
        for (TrackTask trackTask : trackTaskList) {
            //更改状态
            trackTaskService.endTrack(trackTask,now);
            String taskAndDeviceId = trackTask.getTaskId() + "_" + trackTask.getDeviceId();
            if (!taskDeviceSet.contains(taskAndDeviceId)) {
                //发送消息
                try {
                    CameraConfig cameraConfig = cameraConfigService.findByDeviceId(trackTask.getDeviceId());
                    if (cameraConfig != null) {
                        EdgeEndTrackingEvent edgeEndTrackingEvent = new EdgeEndTrackingEvent(systemConfig.getEdgeId(), trackTask.getDeviceId(), trackTask.getTaskId());
                        String responseMsg = objectMapper.writeValueAsString(edgeEndTrackingEvent);
                        MQTTClientUtils.publish(MQTTClientUtils.LOCAL_MQTT_CLIENT, cameraConfig.getDispatcherTopic(), CacheConstants.DEFAULT_QOS, responseMsg);
                    } else {
                        log.error("设备不存在,设备ID:{}", trackTask.getDeviceId());
                    }
                } catch (Exception e) {
                    log.error("边缘中心发送停止跟踪消息发生异常,任务ID:{}, 设备ID:{}", trackTask.getTaskId(), trackTask.getDeviceId(), e);
                }
                taskDeviceSet.add(taskAndDeviceId);
            }
        }
    }

    @Override
    @Async("miniThreadPoolTaskExecutor")
    public void endTracking(String taskId, String deviceId) {
        List<TrackTask> trackTaskList =  trackTaskService.findByTaskIdAndDeviceId(taskId,deviceId);
        if(trackTaskList.size()>0){
            trackTaskService.endTrackByTaskIdAndDeviceId(taskId,deviceId,new Date());
            CameraConfig cameraConfig = cameraConfigService.findByDeviceId(deviceId);
            if(cameraConfig==null){
                log.error("设备不存在,设备ID:{}",deviceId);
            }else {
                try {
                    SystemConfig systemConfig = systemConfigService.getSystemConfig();
                    EdgeEndTrackingEvent edgeEndTrackingEvent = new EdgeEndTrackingEvent(systemConfig.getEdgeId(), deviceId, taskId);
                    String responseMsg = objectMapper.writeValueAsString(edgeEndTrackingEvent);
                    MQTTClientUtils.publish(MQTTClientUtils.LOCAL_MQTT_CLIENT, cameraConfig.getDispatcherTopic(), CacheConstants.DEFAULT_QOS, responseMsg);
                } catch (Exception e) {
                    log.error("结束跟踪任务发生异常。 任务ID:{}, 设备ID:{}",taskId,deviceId,e);
                }
            }
        }
    }

    /**
     * 判断无人机是否在相机追踪范围内
     *
     * @param cameraConfig 设备
     * @param uavLng       无人机经度
     * @param uavLat       无人机纬度
     * @param uavAltitude  无人机海拔
     * @return 是否在追踪范围内
     */
    @Override
    public boolean inTrackingRange(CameraConfig cameraConfig, double uavLng, double uavLat, double uavAltitude) {
        double cameraLat = NumberUtil.parseDouble(cameraConfig.getCameraLatitude());
        double cameraLng = NumberUtil.parseDouble(cameraConfig.getCameraLongitude());
        double cameraAltitude = NumberUtil.parseDouble(cameraConfig.getCameraAltitude());
        double groundDistance = GeoUtils.calculateDistance(cameraLat, cameraLng, uavLat, uavLng);
        double altitudeDistance = Math.abs(uavAltitude - cameraAltitude);
        double distance =  Math.sqrt(Math.pow(groundDistance, 2) + Math.pow(altitudeDistance, 2));
        return cameraConfig.getDetectMaxDist() >= distance;
    }
}
